import Ra
from Tiles import *
import unittest

class PlayerTests( unittest.TestCase ):
    def setUp( self ):
        self._players = [ Ra.Player( None ) for i in xrange( 3 ) ]
        self._board = Ra.Board( self._players )
        self._engine = Ra.RaEngine( self._board , self._players )
	self._tile_bag = self._engine._tile_bag

    def testBag( self ):
        tiles = {}
        tile_bag = self._engine._tile_bag
        while len( tile_bag._tiles ):
            tile = tile_bag.draw()
            if str( tile ) not in tiles:
                tiles[ str( tile ) ] = 0

            tiles[ str( tile ) ] += 1

        self.assert_( tiles[ 'Flood' ] is 12 )
        self.assert_( tiles[ 'River' ] is 25 )
        self.assert_( tiles[ 'God' ] is 8 )
        self.assert_( tiles[ 'Ra' ] is 30 )
        self.assert_( tiles[ 'Pharaoh' ] is 25 )
        self.assert_( tiles[ 'Gold' ] is 5 )
        self.assert_( tiles[ 'Drought' ] is 2 )
        self.assert_( tiles[ 'Earthquake' ] is 2 )
        self.assert_( tiles[ 'Pestilence' ] is 2 )
        self.assert_( tiles[ 'Famine' ] is 4 )
        self.assert_( tiles[ 'Green Civ' ] is 5 )
        self.assert_( tiles[ 'Gray Civ' ] is 5 )
        self.assert_( tiles[ 'Red Civ' ] is 5 )
        self.assert_( tiles[ 'Blue Civ' ] is 5 )
        self.assert_( tiles[ 'Yellow Civ' ] is 5 )
        self.assert_( tiles[ 'Monument(0)' ] is 5 )
        self.assert_( tiles[ 'Monument(1)' ] is 5 )
        self.assert_( tiles[ 'Monument(2)' ] is 5 )
        self.assert_( tiles[ 'Monument(3)' ] is 5 )
        self.assert_( tiles[ 'Monument(4)' ] is 5 )
        self.assert_( tiles[ 'Monument(5)' ] is 5 )
        self.assert_( tiles[ 'Monument(6)' ] is 5 )
        self.assert_( tiles[ 'Monument(7)' ] is 5 )

    def testPharaohs( self ):
        players = self._players

        players[0].acquire_tiles( [ PharaohTile() , PharaohTile() ] )
        players[1].acquire_tiles( [ PharaohTile() ] )
        players[2].acquire_tiles( [] )

        self.assertEqual( 0 , players[0].score( players , 1 ) )
        self.assertEqual( -5 , players[1].score( players , 1 ) )
        self.assertEqual( -7 , players[2].score( players , 1 ) )

    def testCivs( self ):
        player = self._players[0]

        player.acquire_tiles( [ CivTile( 0 ) , CivTile( 1 ) , CivTile( 2 ) , CivTile( 3 ) , CivTile( 4 ) ] )
        self.assertEqual( 15 , player.score( [] , 1 ) )
        player.wipe_tiles()

        player.acquire_tiles( [ CivTile( 0 ) , CivTile( 1 ) , CivTile( 2 ) , CivTile( 4 ) ] )
        self.assertEqual( 10 , player.score( [] , 1 ) )
        player.wipe_tiles()

        player.acquire_tiles( [ CivTile( 0 ) , CivTile( 2 ) , CivTile( 4 ) ] )
        self.assertEqual( 5 , player.score( [] , 1 ) )
        player.wipe_tiles()

        player.acquire_tiles( [ CivTile( 2 ) , CivTile( 4 ) ] )
        self.assertEqual( 0 , player.score( [] , 1 ) )
        player.wipe_tiles()

        player.acquire_tiles( [ CivTile( 2 ) ] )
        self.assertEqual( 0 , player.score( [] , 1 ) )
        player.wipe_tiles()

        player.acquire_tiles( [] )
        self.assertEqual( -5 , player.score( [] , 1 ) )
        player.wipe_tiles()

        player.acquire_tiles( [ CivTile( 0 ) , CivTile( 2 ) , CivTile( 4 ) , CivTile( 4 ) , CivTile( 4 ) , CivTile( 4 ) , CivTile( 2 ) ] )
        self.assertEqual( 5 , player.score( [] , 1 ) )
        player.wipe_tiles()


    def testMonuments( self ):
        player = self._players[0]

        player.acquire_tiles( [ MonumentTile( 0 ) , MonumentTile( 0 ) , MonumentTile( 0 ) , MonumentTile( 0 ) , MonumentTile( 0 ) ] )
        self.assertEqual( -5 , player.score( [] , 1 ) )
        self.assertEqual( 11 , player.score( [] , 3 ) )

        player.acquire_tiles( [ MonumentTile( 1 ) , MonumentTile( 1 ) ] )
        self.assertEqual( -5 , player.score( [] , 1 ) )
        self.assertEqual( 12 , player.score( [] , 3 ) )

        player.acquire_tiles( [ MonumentTile( 2 ) , MonumentTile( 2 ) , MonumentTile( 2 ) ] )
        self.assertEqual( -5 , player.score( [] , 1 ) )
        self.assertEqual( 18 , player.score( [] , 3 ) )

        player.acquire_tiles( [ MonumentTile( 3 ) , MonumentTile( 4 ) , MonumentTile( 5 ) ] )
        self.assertEqual( -5 , player.score( [] , 1 ) )
        self.assertEqual( 21 , player.score( [] , 3 ) )

        player.acquire_tiles( [ MonumentTile( 6 ) ] )
        self.assertEqual( -5 , player.score( [] , 1 ) )
        self.assertEqual( 25 , player.score( [] , 3 ) )

        player.acquire_tiles( [ MonumentTile( 7 ) ] )
        self.assertEqual( -5 , player.score( [] , 1 ) )
        self.assertEqual( 30 , player.score( [] , 3 ) )

    def testScoring( self ):
        players = self._players
        player = players[0]

        player._suns.append( Ra.Sun( 20 ) ) #Ensure they get +5 for winning the suns in round 3
        player.acquire_tiles( [ FloodTile() , FloodTile() , RiverTile() , GoldTile() , PharaohTile() , GodTile() ] )
        player.acquire_tiles( [ CivTile( 2 ) , CivTile( 2 ) , CivTile( 3 ) , CivTile( 4 ) ] )
        player.acquire_tiles( [ MonumentTile( 1 ) , MonumentTile( 1 ) , MonumentTile( 1 ) , MonumentTile( 2 ) ] )

        #+3 from Flood/Rivers
        #+3 from Gold
        #+5 from Pharaohs
        #+2 from God
        #+5 from Civs
        #+5 from Suns in third epoch
        #+2 from Unique Monuments in third epoch
        #+5 from Identical Monuments in third epoch
        self.assertEqual( 18 , player.score( players , 1 ) )
        self.assertEqual( 18 , player.score( players , 2 ) )
        self.assertEqual( 30 , player.score( players , 3 ) )

        player.wipe_tiles() #Wipe away the tiles that don't persists between epochs, Floods, Civs, Golds, Gods

        #-3 from Floods
        #-3 from Gold
        #-2 from God
        #-10 from Civs
        self.assertEqual( 0 , player.score( players , 1 ) )
        self.assertEqual( 0 , player.score( players , 2 ) )
        self.assertEqual( 12 , player.score( players , 3 ) )

    def testDrought( self ):
	player = self._players[0]

	player.acquire_tiles( [ FloodTile() , RiverTile() ] )
	player.acquire_tiles( [ DroughtTile() ] )
	self.assertEqual( 0 , len( player._destructive ) )
	self.assertEqual( 0 , len( player.floods() ) )

	player.acquire_tiles( [ DroughtTile() , FloodTile() , FloodTile() , RiverTile() ] )
	self.assertEqual( 0 , len( player.floods() ) )
	self.assertEqual( 1 , len( player.rivers() ) )

	player.acquire_tiles( [ RiverTile() , DroughtTile() ] )
	player.acquire_tiles( [ RiverTile() , FloodTile() ] )
	self.assertEqual( 1 , len( player.rivers() ) )
	self.assertEqual( 1 , len( player.floods() ) )

    def testPestilence( self ):
	player = self._players[0]

	player.acquire_tiles( [ PharaohTile() , PharaohTile() , PharaohTile() , PharaohTile() , PharaohTile() ] )
	player.acquire_tiles( [ PestilenceTile() , PestilenceTile() ] )
	self.assertEqual( 1 , len( player.pharaohs() ) )

	player.acquire_tiles( [ PharaohTile() , PestilenceTile() ] )
	self.assertEqual( 0 , len( player.pharaohs() ) )

    def testBidding( self ):
	board = self._board
	tile_bag = self._tile_bag
	players = self._players
	def sunSortKey( player ):
	    return player.high_sun()

	players.sort( key = sunSortKey )

	class BidHighController:
	    def __init__( self , player ):
		self._player = player
	    def bid( self , tiles , board_sun , bid_history , forced_to_bid ):
		return self._player.high_sun()

	for player in players:
	    player._controller = BidHighController( player )

	board.tiles().extend( [ FloodTile() , RiverTile() , FloodTile() , PharaohTile() , 
				PestilenceTile() , DroughtTile() , MonumentTile( 2 ) , CivTile( 1 ) ] )

	ra = Ra.Ra( players[-1] , True )
	ra.operate( board , tile_bag , players )
	self.assertEqual( 13 , self._board.sun().value() )
	
	winning_bidder = players[-1]
	player_usable_suns = []
	unusable_sun_value = -1
	for player in players:
	    usable_suns = 0
	    for sun in player.suns():
		if sun.usable():
		    usable_suns += 1
		else:
		    unusable_sun_value = sun.value()

	    player_usable_suns.append( ( usable_suns ) )

	self.assertEqual( 4 , player_usable_suns[0] )
	self.assertEqual( 4 , player_usable_suns[1] )
	self.assertEqual( 3 , player_usable_suns[2] )
	self.assertEqual( 1 , unusable_sun_value )

	self.assertEqual( 0 , len( winning_bidder.floods() ) )
	self.assertEqual( 1 , len( winning_bidder.rivers() ) )
	self.assertEqual( 0 , len( winning_bidder.pharaohs() ) )
	self.assertEqual( 1 , len( winning_bidder.monuments() ) )
	self.assertEqual( 1 , len( winning_bidder.civs() ) )

if __name__ == '__main__':
    unittest.main()
